import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:web_socket_channel/io.dart';

class WebRTCPage extends StatefulWidget {
  const WebRTCPage({super.key});

  @override
  _WebRTCPageState createState() => _WebRTCPageState();
}

class _WebRTCPageState extends State<WebRTCPage> {
  late IOWebSocketChannel channel;
  RTCPeerConnection? pc;
  bool isInitiator = false;

  @override
  void initState() {
    super.initState();
    connectToWebSocket();
  }

  void connectToWebSocket() {
    channel = IOWebSocketChannel.connect('ws://192.168.17.13:8080/ws');
    channel.stream.listen((message) {
      handleSignalingMessage(message);
    });
  }

  void handleSignalingMessage(String message) {
    Map<String, dynamic> data = json.decode(message);
    switch (data['type']) {
      case 'offer':
        handleOffer(data['sdp']);
        break;
      case 'answer':
        handleAnswer(data['sdp']);
        break;
      case 'candidate':
        handleCandidate(data['candidate']['candidate']);
        break;
    }
  }

  void handleOffer(String sdp) async {
    RTCSessionDescription offer = RTCSessionDescription(sdp, 'offer');
    await pc!.setRemoteDescription(offer);
    RTCSessionDescription answer = await pc!.createAnswer();
    await pc!.setLocalDescription(answer);
    sendSignalingMessage({'type': 'answer', 'sdp': answer.sdp});
  }

  void handleAnswer(String sdp) async {
    RTCSessionDescription answer = RTCSessionDescription(sdp, 'answer');
    await pc!.setRemoteDescription(answer);
  }

  void handleCandidate(String candidate) async {
    RTCIceCandidate iceCandidate = RTCIceCandidate(candidate, 'mid', 0);
    await pc!.addCandidate(iceCandidate);
  }

  void sendSignalingMessage(Map<String, dynamic> message) {
    channel.sink.add(json.encode(message));
  }

  Future<void> createOffer() async {
    pc = await createPeerConnection({});
    pc!.onIceCandidate = (RTCIceCandidate candidate) {
      if (candidate.candidate!.isNotEmpty) {
        sendSignalingMessage({'type': 'candidate', 'candidate': candidate.toMap()});
      }
    };
    RTCSessionDescription offer = await pc!.createOffer();
    await pc!.setLocalDescription(offer);
    sendSignalingMessage({'type': 'offer', 'sdp': offer.sdp});
  }

  Future<void> initializePeerConnection() async {
    pc = await createPeerConnection({});

    pc!.onIceConnectionState = (RTCIceConnectionState state) {
      print("RTCIceConnectionState: $state");
      if (state == RTCIceConnectionState.RTCIceConnectionStateFailed) {
        print("ICE connection failed!");
      } else if (state == RTCIceConnectionState.RTCIceConnectionStateConnected) {
        print("ICE connection connected!");
      } else if (state == RTCIceConnectionState.RTCIceConnectionStateCompleted) {
        print("ICE connection completed!");
      }
    };

    pc!.onIceCandidate = (RTCIceCandidate candidate) {
      if (candidate.candidate!.isNotEmpty) {
        sendSignalingMessage({'type': 'candidate', 'candidate': candidate.toMap()});
      }
    };
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('WebRTC Client')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () async {
                setState(() {
                  isInitiator = true;
                });
                await createOffer();
              },
              child: Text('Create Offer'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                setState(() {
                  isInitiator = false;
                });
                await initializePeerConnection();
              },
              child: Text('Wait for Offer'),
            ),
          ],
        ),
      ),
    );
  }
}